<?php

/**
 * This file is part of the Codizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Codizer Core Team <team@codizer.org>
 * @package     Codizer
 */

class f_core_Request
{
	const GET = 'GET';
	const POST = 'POST';
	
	private $session;
	
	private static $instance;
	
	private $parameters = array();
	
	private function __construct()
	{
		if(isset($_SERVER['REQUEST_METHOD']))
		{
			switch ($_SERVER['REQUEST_METHOD'])
			{
				case 'GET':
					$request = $_GET;
					break;
				case 'POST':
					$request = array_merge($_GET, $_POST);
			}
			$this->getDatasFromRequest($request);			
		}
	}
	
	/**
	 * @return f_core_Request
	 */
	static function getInstance()
	{
		if (self::$instance === null)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	/**
	 * Retrieve all data from $_GET and $_POST and set into class values
	 * 
	 * @param array<String, mixed> $map
	 */
	protected final function getDatasFromRequest($request)
	{
		if(is_array($request))
		{
			$logger = f_logs_Logger::getInstance();
			$req = array();
			
			foreach ($request as $key => $value)
			{
				if (is_array($value))
				{
					$this->parameters[$key] = $value;
				}
				else
				{
					$req[] = $key."=".$value;
					$this->parameters[$key] = array($value);
				}
			}
		}
	}

    public function getBrowserInfos($agent = null)
    {
        $known = array('msie', 'firefox', 'safari', 'webkit', 'opera', 'netscape', 'konqueror', 'gecko');

        $agent = strtolower($agent ? $agent : $_SERVER['HTTP_USER_AGENT']);
        $pattern = '#(?<browser>' . join('|', $known).')[/ ]+(?<version>[0-9]+(?:\.[0-9]+)?)#';

        if (!preg_match_all($pattern, $agent, $matches)) return array();

        $i = count($matches['browser'])-1;

        $result = array();

        $result['browser'] = $matches['browser'][$i];
        $result['version'] = $matches['version'][$i];
        $result['engine'] = $matches['browser'][0];

        return $result;
    }
	
	/**
	 * Retrieve a request parameter
	 * 
	 * @param string $name
	 * @param string $defaultValue
	 * @return string|null
	 */
	public function getParameter($name, $defaultValue = null)
	{
		if (isset($this->parameters[$name]))
		{
			if(isset($this->parameters[$name][1]))
			{
				return $this->parameters[$name];
			}
			else
			{
				return $this->parameters[$name][0];
			}
		}
		return $defaultValue;
	}
	
	/**
	 * Set an additional request parameter (useful for routing)
	 * 
	 * @param $name
	 * @param $value
	 * @return f_core_Request
	 */
	public function setParameter($name, $value)
	{
		$this->parameters[$name] = $value;
		return $this;
	}
		
	/**
	 * Retrieve all request parameters in an array
	 * 
	 * @return array
	 */
	public function getParameters()
	{
		return $this->parameters;
	}
	
	/**
	 * Retrieve all values for a parameter in array (forms)
	 * 
	 * @param string $name
	 * @return array|null
	 */
	public function getParameterValues($name)
	{
		if (isset($this->parameters[$name]))
		{
			return $this->parameters[$name];
		}
		return null;
	}	
	
	/**
	 * Set a request attribute (additional datas for request)
	 * 
	 * @param string $name
	 * @param mixed $value
	 */
	public function setAttribute($name, $value)
	{
		$this->attributes[$name] = $value;
	}
	
	/**
	 * Get a request attribute (additional datas for request)
	 * 
	 * @param string $name
	 * @param mixed $defaultValue
	 * @return mixed
	 */
	public function getAttribute($name, $defaultValue = null)
	{
		if (isset($this->attributes[$name]))
		{
			return $this->attributes[$name];
		}
		return $defaultValue;
	}
	
	/**
	 * Retrieve all additional attributes from request
	 * 
	 * @return array
	 */
	public function getAttributes()
	{
		return $this->attributes;
	}
	
	/**
	 * Get the current session
	 * 
	 * @return core_HttpSession
	 */
	public function getSession()
	{
		if ($this->session === null)
		{
			$this->session = new f_core_Session();
		}
		return $this->session;
	}
	
	/**
	 * Check if a parameter exist in request
	 * 
	 * @param string $name
	 * @return boolean 
	 */
	public function hasParameter($name)
	{
		return array_key_exists($name, $this->parameters);
	}
	
	/**
	 * Check if a parameter in request have a value
	 * 
	 * @param string $name
	 * @return boolean
	 */
	public function hasNonEmptyParameter($name)
	{
		return $this->hasParameter($name);
	}
	
	/**
	 * Check if the request has the given attribute
	 * 
	 * @param string $name
	 * @return boolean
	 */
	public function hasAttribute($name)
	{
		return array_key_exists($name, $this->attributes);
	}
}